package com.dynamic.mybatis.core.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.dynamic.mybatis.core.metadata.MappedStatementMetaField;
import net.sf.cglib.beans.BeanMap;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author xs
 * @Date 2023/4/24 9:29
 */
public class TreeUtil {
    public static final String childrenKey = "children";
    public static final String idKey = "id";
    public static final String parentIdKey = "parentId";
    public static final int rootParentId = 0;

    /**
     * @param tree     被转换对象
     * @param childKey 节点的子字段名
     *                 　* @return 集合结构
     *
     * @Description: tree 转 list
     */
    public static <T> List<T> toArray(Object tree, String childKey) {
        if (tree == null) {
            return Collections.EMPTY_LIST;
        }
        Collection<T> treeList = tree instanceof Collection ? (Collection) tree : Arrays.asList((T) tree);
        List<T> result = new ArrayList<>();
        for (T entity : treeList) {
            result.add(entity);
            Map beanMap = entity instanceof Map ? (Map) entity : BeanMap.create(entity);
            List<Object> children = (List<Object>) beanMap.get(childKey);
            if (children != null && children.size() > 0) {
                result.addAll(toArray(children, childKey));
            }
        }
        if (result.size() > 0) {
            for (int i = 0; i < result.size(); i++) {
                Map beanMap = BeanUtils.copyGetMap(result.get(i));
                beanMap.put(childKey, null);
                result.set(i, BeanUtils.getBean(beanMap));
            }
        }
        return result;
    }

    public static <T> T setTree(T tree) {
        return setTree(tree, rootParentId, parentIdKey, idKey, childrenKey);
    }

    /**
     * @param tree         被转换对象
     * @param rootParentId 根节点的父字段对应的值
     * @param parentIdKey  节点的父字段名
     * @param idKey        节点的唯一字段名
     * @param childKey     节点的子字段名
     *                     　* @return 树形结构
     *
     * @Description: 给具有层级关系的树结构的id, parentId字段赋值
     */
    public static <T> T setTree(T tree, int rootParentId, String parentIdKey, String idKey, String childKey) {
        return setTree(tree, rootParentId, new AtomicInteger(rootParentId), parentIdKey, idKey, childKey);
    }

    public static <T> T setTree(T tree, int rootParentId, AtomicInteger startId, String parentIdKey, String idKey, String childKey) {
        if (tree == null) {
            return tree;
        }
        Collection<Object> treeList = tree instanceof Collection ? (Collection) tree : Arrays.asList(tree);
        for (Object entity : treeList) {
            Map beanMap = entity instanceof Map ? (Map) entity : BeanMap.create(entity);
            startId.set(startId.get() + 1);
            beanMap.put(idKey, startId.get());
            beanMap.put(parentIdKey, rootParentId);
            setTree(beanMap.get(childKey), (int) beanMap.get(idKey), startId, parentIdKey, idKey, childKey);
        }
        return tree;
    }


    public static <T> List<T> toTree(Object array) {
        return toTree(array, rootParentId, parentIdKey, idKey, childrenKey);
    }


    /**
     * 　* @Description: list 转 tree
     * 　* @param array 被转换对象
     *
     * @param parentId    根节点的父字段对应的值
     * @param parentIdKey 节点的父字段名
     * @param idKey       节点的唯一字段名
     * @param childKey    节点的子字段名
     *                    　* @return 树形结构
     *
     */
    public static <T> List<T> toTree(Object array, Object parentId, String parentIdKey, String idKey, String childKey) {
        Collection<T> treeList = array instanceof Collection ? (Collection) array : Arrays.asList((T) array);
        List<T> list = treeList.stream()
                // 过滤父节点
                .filter(parent -> Objects.equals(BeanUtils.beanToMap(parent).get(parentIdKey), parentId))
                // 把父节点children递归赋值成为子节点
                .map(child -> {
                    Map childMap = BeanUtils.beanToMap(child);
                    childMap.put(childKey, toTree(treeList, childMap.get(idKey), parentIdKey, idKey, childKey));
                    return child;
                }).collect(Collectors.toList());
        return list;
    }

    public static void main(String[] args) {
        String idKey = "id";
        String parentKey = "parentId";
        String childKey = "children";

        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("id", 1);
        map1.put("parentId", 0);
        map1.put("name", "1");


        Map<String, Object> map2 = new HashMap<>();
        map2.put("id", 2);
        map2.put("parentId", 1);
        map2.put("name", "2");

        Map<String, Object> map3 = new HashMap<>();
        map3.put("id", 3);
        map3.put("parentId", 2);
        map3.put("name", "3");


        Map<String, Object> map4 = new HashMap<>();
        map4.put("id", 4);
        map4.put("parentId", 0);
        map4.put("name", "4");

        list.add(map1);
        list.add(map2);
        list.add(map3);
        list.add(map4);


        List<Object> tree = toTree(list, 0, "parentId", "id", "children");

        List<MappedStatementMetaField> fieldTree = JSON.parseArray(JSON.toJSONString(tree), MappedStatementMetaField.class);

        System.out.println("1 ====================================== ");
        setTree(fieldTree, -10, "parentId", "id", "children");
        System.out.println("  " + JSON.toJSONString(fieldTree, JSONWriter.Feature.PrettyFormat));
        System.out.println("1 ====================================== ");


        System.out.println("  " + JSON.toJSONString(tree, JSONWriter.Feature.PrettyFormat));

        List<Object> array = toArray(fieldTree, "children");


        System.out.println(JSON.toJSONString(array, JSONWriter.Feature.PrettyFormat));

    }

}